<template>
  <a-upload
    :file-list="fileList"
    action="#"
    name="fileName"
    :list-type
    :accept
    :maxCount
    :show-upload-list
    :disabled
    :multiple
    :before-upload="beforeUpload"
    :customRequest="customRequest"
    @preview="handlePreview"
    @remove="handleRemove"
    @change="handleChange"
  >
    <div v-if="fileList.length < 1">
      <loading-outlined v-if="loading"></loading-outlined>
      <plus-outlined v-else></plus-outlined>
      <div>{{ uploadText }}</div>
    </div>
  </a-upload>
  <a-image
    :width="200"
    :style="{ display: 'none' }"
    :preview="{
      visible: imgVisible,
      onVisibleChange: setVisible,
    }"
    :src="imageUrl"
    fallback="@/assets/images/not-imag.png"
  />
</template>

<script setup lang="ts">
import { FileService } from '@/api'
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue'
import { fileMd5 } from '@/utils/file-tools'
import type { Props, Emits } from './file.interface'
import type { UploadProps, UploadFile, UploadChangeParam } from 'ant-design-vue'

defineOptions({ name: 'UploadFile' })

/**组件入参 */
const { multiple = false, accept = '*', disabled = false, maxCount = 1, showUploadList = true, listType = 'picture-card', uploadText = '点击上传' } = defineProps<Props>()
/** 组件自定义事件 */
const emit = defineEmits<Emits>()

/** 文件列表 */
const fileList = defineModel<UploadFile[]>('fileList', { type: Array<UploadFile>, default: [] })

const loading = ref<boolean>(false)
const imageUrl = ref<string>('')

// 判断文件是否为图片类型
function isImage(file: any): boolean {
  const type = file.type as string
  return type.startsWith('image/')
}

function isAcceptPart(fileType: string): boolean {
  const acceptParts = accept.split(',') || []
  console.log('isAcceptPart:==>', fileType, acceptParts)
  return acceptParts.some((v) => {
    return fileType.split('/').some((type) => v.includes(type))
  })
}

// 上传文件前校验
function beforeUpload(file: any): boolean {
  console.log('beforeUpload:==>', file)
  loading.value = true
  const fileType = file.type as string
  // 校验文件类型
  const isAcceptedType = accept === '*' || isAcceptPart(fileType)
  if (!isAcceptedType) {
    window.$message.error(`只能上传以下格式的文件: ${accept}`)
    loading.value = false
    return false
  }
  if (isImage(file)) {
    const isLt1M = file.size / 1024 / 1024 < 1
    if (!isLt1M) {
      window.$message.error('图片大小不能超过 1MB!')
      loading.value = false
      return false
    }
  }
  return true
}

// 删除文件
function handleRemove(file: UploadFile): UploadProps['onRemove'] {
  const index = fileList.value.indexOf(file)
  const newFileList = fileList.value.slice()
  console.log('删除文件:==>', file, index, newFileList)
  newFileList.splice(index, 1)
  fileList.value = newFileList
  emit('remove', file)
  return void 0
}

function handleChange({ file, fileList }: UploadChangeParam) {
  console.log('handleChange===', file, fileList)
}

// 自定义上传文件方法
async function customRequest(e: any) {
  const file = e.file
  const fileName = encodeURIComponent(file.name)
  console.log('自定义上传:==>', file, fileName)
  if (isImage(file)) {
    const dataurl = await getFileDataUrl(file)
    // console.log('dataurl:==>', dataurl)
    imageUrl.value = dataurl
    emit('getDataUrl', imageUrl.value)
  }
  const md5 = await getFileMd5(file)
  console.log('文件md5值:==>', md5)
  const formData = new FormData()
  formData.append('file', file)
  formData.append('fileName', fileName)
  formData.append('digest', md5)
  FileService.upload(formData).then((res) => {
    loading.value = false
    console.log('上传结果:==>', res)
    const { data } = res
    if (data) {
      fileList.value.push({
        uid: data.id,
        name: file.name,
        status: 'done',
        url: data.url,
        thumbUrl: imageUrl.value,
      })
    }
    console.log('customRequest-fileList', fileList.value)
    emit('success', data)
  })
}

function getFileMd5(file: File): Promise<string> {
  return new Promise((resolve) => {
    fileMd5(file, (md5) => {
      resolve(md5)
    })
  })
}

function getFileDataUrl(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    try {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = (e) => {
        const dataurl = e.target?.result as string
        resolve(dataurl)
      }
    } catch (error) {
      reject(error)
    }
  })
}
// 设置图片预览是否显示
const imgVisible = ref<boolean>(false)
function setVisible(value: boolean): void {
  imgVisible.value = value
}
// 文件预览
const handlePreview = async (file: any) => {
  console.log('文件预览:==>', file)
  const fileType = file.url?.split('.').at(-1)
  const imgs = ['png', 'jpg', 'jpeg', 'gif', 'bmp']
  if (imgs.includes(fileType)) {
    if (file.thumbUrl) {
      imageUrl.value = file.thumbUrl
    } else {
      imageUrl.value = file.url
    }
    setVisible(true)
  }
}
onMounted(() => {})
</script>

<style lang="scss" scoped></style>
